package perf.parse.valgrind;

import java.util.Date;

import perf.data.Binary;
import perf.data.Callcosts;
import perf.data.Function;
import perf.data.InlineCost;
import perf.data.Linecosts;
import perf.data.Run;
import perf.data.Sourcefile;

public class ObjectState {

	private final static boolean DEBUG = false;
	//if this is set, then it means that this object
	//is tracking the call destination.
	private final ObjectState sourceState;
	private final boolean isDestination;

	private Run run;
	private Binary object;
	private Sourcefile file;
	private Function function;	
	private Sourcefile inline;
	
	public ObjectState( ObjectState src, Run run ) {
		this.run = run;
		this.sourceState = src;
		isDestination = true;
	}
	
	public ObjectState( Run run ) {
		this.run = run;
		this.sourceState = null;
		isDestination = false;
	}
	public void setObject( String objectString ) {
		object = run.getBinaryInstance( objectString );
		file = null;
		function = null;
		inline = null;
		
		debug( "setObject = " + objectString );
	}

	public void setFile( String filestring ) {
		file = getObject().getSourceInstance( filestring );
		//when inline is set, then unset it and keep the current function
		if ( inline != null ) {
			//the fe tag indicates also the end of inlined code
			inline = null;
		} else {
			function = null;
		}
		
		debug( "setFile = " + filestring );
	}
	
	public void setFunction( String function ) {
		this.function = getFile().getFunctionInstance( function );
		inline = null;
		
		debug( "setFunction = " + function );
	}
	
	public void setInline( String inline ) {
		this.inline = object.getSourceInstance( inline );
		
		debug( "setInline = " + inline );
	}
	
	public void setRundate( Date date) {
		run.setRunDate( date );
	}
	
	public void setLineCosts( int linenum, long[] costs ) {
		Linecosts lc = getFunction().getLinecostInstance( linenum );
		
		lc.updateCosts( costs );
		
		debug( "setCosts for line " + linenum +  " = " + costs[0] );
	}

	public void setCallCosts( int srcLine, int destLine, Function dest, long calls, long[] costs ) {
		Callcosts cc;
		cc =getFunction().getLinecostInstance( srcLine ).getCallcostsInstance(dest);
		
		cc.setCalls( calls );
		cc.setSourceLine( srcLine );
		cc.updateCosts( costs );
		cc.setDestinationLine( destLine );
		debug( "setCallCosts to " + dest.getName() );
	}
	
	public void setInlineCosts( int linenum, long[] costs ) {
		InlineCost ic = getFunction().getInlineCostInstance( inline, linenum );
		
		ic.getLinecostInstance(linenum).updateCosts(costs);
		
		debug( "setCosts for inline " + linenum + " = " + costs[0] );
	}
	
	public void setDescription( String tag, String val ) {
		run.addDescription( tag, val );
	}
	
	public void reset( ) {
		object = null;
		file = null;
		function = null;
		inline = null;
	}

	public Binary getObject() {
		if ( object == null && isDestination ) {
			return sourceState.getObject();
		} else {
			return object;
		}
	}

	public Sourcefile getFile() {
		if ( file == null && isDestination ) {
			return sourceState.getFile();
		} else {
			return file;
		}
	}

	public Function getFunction() {
		if ( function == null && isDestination ) {
			return sourceState.getFunction();
		} else {
			return function;
		}
	}
	
	private void debug( String s ) {
		if (DEBUG) {
			String name = isDestination ? "dst" : "src";
			System.out.println( name + ": " + s );
		}
	}
}
